﻿/*
 * Copyright 2015 Rene Prost, Registrite ja Infosüsteemide Keskus 
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * 
 */
using System;
using System.IO;
using Xtee.Core.Mime;

namespace Xtee.Core
{

    public abstract class MultipartFile
    { 
        protected MultipartFile()
        {
            this.MimeType = "application/octet-stream";
            this.CreationTime = DateTime.Now;
        }
        internal abstract Stream Create();
        public abstract Stream OpenRead();
        public abstract string Name { get; }
        public abstract long Length { get; }
        public virtual string MimeType { get; protected set; }
        public virtual DateTime CreationTime { get; protected set; }
        internal abstract object Target {get;}

        public abstract byte[] AllBytes();

        public abstract bool Exists { get; }
         
        internal static MultipartFile CreateTemporaryFile(Storage storage)
        {
            if (!storage.TempInMemory) {
                var path = System.IO.Path.Combine(storage.TempRoot, Guid.NewGuid().ToString().Replace("-", "") + ".tmp");
                return new MultipartFileInfo(new FileInfo(path));
            }
            else
            {
                return new MultipartInMemoryInfo();
            }
            
        }
         
        public static MultipartFile Create(FileInfo fileinfo)
        {
            return new MultipartFileInfo(fileinfo);
        }

        public static MultipartFile Create(byte[] bytes)
        {
            return new MultipartInMemoryInfo(bytes);
        }

        public static implicit operator FileInfo(MultipartFile file) 
        {
            if (file == null) return null;
            return (FileInfo)((MultipartFileInfo)file).Target;
        }
        public static implicit operator MultipartFile(FileInfo file)
        {
            if (file == null) return null;
            return MultipartFileInfo.Create(file);
        }

         
        public class MultipartFileInfo : MultipartFile
        {
            private FileInfo file;
            
            public MultipartFileInfo(FileInfo file)
            {
                this.file = file;
            }

            internal override Stream Create()
            {
                return file.Create();
            }

            public override Stream OpenRead()
            {
                return File.OpenRead(file.FullName);
            }

            public override string Name
            {
                get
                {
                    return file.Name;
                }
            }

            public override long Length
            {
                get
                {
                    return file.Length;
                }
            }

            public override string MimeType
            {
                get
                {
                    return MimeTypes.GetMimeType(file.FullName);
                }
            }

            public override DateTime CreationTime
            {
                get
                {
                    return file.CreationTime;
                }
            }

            public override byte[] AllBytes()
            {
                return File.ReadAllBytes(file.FullName);
            }

            internal override object Target
            {
                get
                {
                    return file;
                }
            }

            public override bool Exists
            {
                get { return file.Exists; }
            }

            public override string FullName
            {
                get { return file.FullName; }
            }

            public override DirectoryInfo Directory
            {
                get { return file.Directory; }
            }
        }

         
        private class MultipartInMemoryInfo : MultipartFile
        {
            MultipartMemoryStream stream;
            public MultipartInMemoryInfo(byte[] bytes) {
                stream = new MultipartMemoryStream(bytes);
            }
            public MultipartInMemoryInfo()
            {
               
            }
            internal override Stream Create()
            {
                stream =  new MultipartMemoryStream();
                return stream;
            }

            public override Stream OpenRead()
            {
                return stream.OpenRead();
            }

            public override string Name
            {
                get { return "InMemoryAttachment"; }
            }

            public override long Length
            {
                get { return stream.Length; }
            }

            internal override object Target
            {
                get { return stream; }
            }

            public override byte[] AllBytes()
            {
                return stream.ToArray();
            }

            public override bool Exists
            {
                get { return stream != null; }
            }

            public override string FullName
            {
                get { throw new NotSupportedException("MemoryStream has no name."); }
            }

            public override DirectoryInfo Directory
            {
                get { throw new NotSupportedException("MemoryStream has no directory."); }
            }
        }


        public abstract string FullName { get;  }

        public abstract DirectoryInfo Directory { get; }
    }


    public class MultipartMemoryStream : MemoryStream
    {
        public MultipartMemoryStream(byte[] bytes) : base(bytes) { 
        
        }

        public MultipartMemoryStream() { 
        
        }

        public Stream OpenRead()
        {
            return new MemoryStream(this.ToArray()); 
        } 
    }
}
